﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NHibernate;
using dbPoll_Application.Helpers;
using NHibernate.Linq;

namespace dbPoll_Application.Models
{
    public class EntityRepository
    {
        /// <summary>
        /// Adds a Entity to the EntityRepository.
        /// </summary>
        /// <param name="user">A Entity to be added.</param>
        /// <returns>Returns true when the Entity was successfully added.</returns>
        public static Boolean Add(Entity entity)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Save(entity);
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        /// <summary>
        /// Updates all attributes of a Entity in the EntityRepository.
        /// </summary>
        /// <param name="user">A Entity to be updated.</param>
        /// <returns>Returns true when the Entity was successfully updated.</returns>
        public static Boolean Update(Entity entity)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.SaveOrUpdate(entity);
                transaction.Commit();
                return transaction.WasCommitted;
            }
        }

        /// <summary>
        /// Gets a collection of all of the Entities in the EntityRepository.
        /// </summary>
        /// <returns>A collection of all the Entities in the EntityRepository.</returns>
        public static IList<Entity> GetEntities()
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var entities = from item in session.Query<Entity>()
                        select item;
            return entities.ToList<Entity>();
        }

        public static Entity GetEntityByEntityID(int entityID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var entity = (from item in session.Query<Entity>()
                          where item.entityID == entityID
                          select item).FirstOrDefault<Entity>();
            return entity;
        }

        public static IList<Entity> GetEntityByEntityIDs(int[] entityIDs)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var entities = (from item in session.Query<Entity>()
                          where entityIDs.Contains(item.entityID)
                          select item).ToList<Entity>();
            return entities;
        }

        public static IList<Entity> GetChildren(Entity parent)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var entities = (from item in session.Query<Entity>()
                          where item.parent == parent
                          select item);
            return entities.ToList<Entity>();
        }

        public static IList<Entity> GetAllChildren(Entity parent)
        {
            return GetAllChildrenRecursive(parent, new List<Entity>());
        }

        private static IList<Entity> GetAllChildrenRecursive(Entity parent, IList<Entity> children)
        {
            IList<Entity> temp = new List<Entity>();
            foreach (var child in children)
            {
                if (!temp.Contains(child))
                    temp.Add(child);
            }

            ISession session = NHibernateHelper.GetCurrentSession();
            var entities = (from item in session.Query<Entity>()
                            where item.parent == parent
                            select item).ToList<Entity>();

            if (entities.Count == 0)
                return temp;

            else
            {
                foreach (var entity in entities)
                {
                    if (!temp.Contains(entity))
                        temp.Add(entity);
                }
                
                foreach (var entity in entities)
                {
                    var grandkids = GetAllChildrenRecursive(entity, temp);
                    foreach (var child in grandkids)
                    {
                        if (!temp.Contains(child))
                            temp.Add(child);
                    }
                }
                return temp;
            }
        }

        public static IList<Entity> GetEndEntities(int pollID)
        {
            ISession session = NHibernateHelper.GetCurrentSession();
            var all = PollRepository.GetPollByID(pollID).entities;
            var entities = (from item1 in all from item2 in all
                            where item2.parent!=null && item1.entityID == item2.parent.entityID
                            select item1);
            var answer = (from item in all where !(entities.Contains(item)) select item);
            return answer.ToList<Entity>();
        }
    }
}
